package admin

import (
	"go-amis-admin/amis"
	"strconv"

	"gorm.io/gorm"
)

type UserModule struct {
	CrudModule[User]
}

func NewUserModule(basePath string) *UserModule {
	// 搜索表单
	filterOptions := &FilterOptions{
		KeywordFields: []string{"Username", "Email", "Mobile"},
		FieldOptions: map[string]amis.Options{
			"Username": {
				"label": "用户名",
			},
			"Email": {
				"label": "邮箱",
			},
			"Mobile": {
				"label": "手机",
			},
			"Status": {
				"label":    "状态",
				"type":     "checkboxes",
				"operator": WhereIn,
				"source":   "/admin/dic/getDetailByType?code=UserStatus",
			},
			"CreatedAt": {
				"label":     "创建时间",
				"type":      "input-date-range",
				"operator":  WhereBetween,
				"valueType": ValueTypeDate,
			},
			"DeptID": {
				"type": "-",
				"operator": func(tx *gorm.DB, k, v string) {
					ids := make([]uint, 0)
					Instance.DB.Raw(`
					WITH RECURSIVE SubDepartments AS (
						SELECT ID,Label, ParentID
						FROM departments
						WHERE id = ?
						UNION ALL
						SELECT d.id, d.Label, d.ParentID
						FROM departments d
						JOIN SubDepartments sd ON d.ParentID = sd.id
					)
					SELECT id
					FROM SubDepartments;
					`, v).Scan(&ids)
					tx.Where("ID in ?", ids)
				},
			},
		},
	}
	columnsOptions := &ColumnsOptions{
		ExcludeFields: []string{"Password"},
		FieldOptions: amis.MultiOptions{
			"Username": {
				"sortable":   true,
				"searchable": true,
			},
			"Mobile": {
				"quickEdit": true,
			},
			"Email": {
				"quickEdit": true,
			},
			"Status": {
				"filterable": true,
				"type":       "mapping",
				"map": amis.Options{
					"*": amis.Options{
						"type": "status",
					},
				},
			},
			"Departemnt": {},
		},
	}
	formOptions := &FormOptions{
		FieldOptions: amis.MultiOptions{
			"DeptID": {
				"type":        "tree-select",
				"source":      "/admin/user/getDeptTree",
				"valueField":  "ID",
				"labelField":  "Label",
				"label":       "部门",
				"validations": "isRequired",
			},
		},
	}
	user := UserModule{
		CrudModule: NewCrudModule("机构人员", "user", "fa fa-user", basePath, 100,
			User{}, formOptions, columnsOptions, filterOptions),
	}
	user.PageSchema["cssVars"] = amis.Options{
		"--Page-aside-width": "18rem",
	}
	user.PageSchema["asideMinWidth"] = 260
	user.PageSchema["asideMaxWidth"] = 460
	user.PageSchema["asideResizor"] = true
	user.PageSchema["aside"] = user.getAsideSchema()

	user.UpdatePage()

	return &user
}

func (u *UserModule) getAsideSchema() amis.Obj {
	treeView := amis.New("input-tree").
		Set("name", "DeptID").
		Set("inputClassName", "no-border no-padder mt-1").
		Set("heightAuto", true).
		Set("submitOnChange", true).
		Set("selectFirst", true).
		Set("inputOnly", true).
		Set("valueField", "ID").
		Set("labelField", "Label").
		Set("creatable", true).
		Set("editable", true).
		Set("addApi", "/admin/user/saveDept").
		Set("editApi", "/admin/user/saveDept").
		Set("removable", true).
		Set("deleteApi", "/admin/user/deleteDept?id=${ID}").
		Set("source", "/admin/user/getDeptTree")

	panel := amis.New("form").
		Set("title", "部门").
		Set("className", "border-0").
		Set("target", "crud").
		Set("submitOnInit", true).
		Set("body", treeView).
		Set("actions", []amis.Obj{})
	return panel
}

func (u *UserModule) GetDeptTreeApi(ctx *AdminContext) {
	var result []*Department
	u.DB.Find(&result)
	tree := buildTree(0, result)

	ctx.Sucess(tree, "")
}

func (u *UserModule) SaveDeptApi(ctx *AdminContext) {
	var dept Department
	if err := ctx.ShouldBindJSON(&dept); err != nil {
		ctx.Fail(err.Error())
		return
	}
	if dept.Parent != nil {
		dept.ParentID = dept.Parent.ID
	}

	if dept.ID == 0 {
		u.DB.Create(&dept)
	} else {
		u.DB.Save(&dept)
	}
	ctx.Sucess(nil, "")
}

func (u *UserModule) DeleteDeptApi(ctx *AdminContext) {
	id, _ := strconv.Atoi(ctx.Query("id"))
	var count int64
	u.DB.Model(&Department{}).Where("ParentID =?", id).Count(&count)
	if count > 0 {
		ctx.Fail("部门下还有子部门，不能删除")
		return
	}
	u.DB.Model(&u.Model).Where("DeptID =?", id).Count(&count)
	if count > 0 {
		ctx.Fail("部门下还有用户，不能删除")
		return
	}
	u.DB.Delete(&Department{}, "id =?", id)
	ctx.Sucess(nil, "")
}

func buildTree(parentId uint, data []*Department) []*Department {
	var tree []*Department
	for _, v := range data {
		if v.ParentID == parentId {
			tree = append(tree, v)
			v.Children = buildTree(v.ID, data)
		}
	}
	return tree
}
